<script setup lang="ts">
import { ref, computed, watch } from 'vue';

// Props
interface Props {
  visible: boolean;
}

const props = defineProps<Props>();

// Emits
const emit = defineEmits<{
  close: [];
}>();

// 响应式数据
const leftJson = ref('');
const rightJson = ref('');
const leftTitle = ref('原始JSON');
const rightTitle = ref('对比JSON');
const showLineNumbers = ref(true);
const ignoreWhitespace = ref(false);
const ignoreCase = ref(false);

// 差异类型
interface DiffLine {
  type: 'equal' | 'added' | 'removed' | 'modified';
  leftLineNumber?: number;
  rightLineNumber?: number;
  leftContent?: string;
  rightContent?: string;
  content?: string;
}

// 计算差异
const diffResult = computed(() => {
  if (!leftJson.value && !rightJson.value) {
    return [];
  }

  try {
    // 格式化JSON
    const leftFormatted = leftJson.value ? JSON.stringify(JSON.parse(leftJson.value), null, 2) : '';
    const rightFormatted = rightJson.value ? JSON.stringify(JSON.parse(rightJson.value), null, 2) : '';
    
    // 按行分割
    const leftLines = leftFormatted.split('\n');
    const rightLines = rightFormatted.split('\n');
    
    return generateDiff(leftLines, rightLines);
  } catch (error) {
    // 如果JSON解析失败，直接按文本对比
    const leftLines = leftJson.value.split('\n');
    const rightLines = rightJson.value.split('\n');
    return generateDiff(leftLines, rightLines);
  }
});

// 生成差异对比
function generateDiff(leftLines: string[], rightLines: string[]): DiffLine[] {
  const result: DiffLine[] = [];
  let leftIndex = 0;
  let rightIndex = 0;
  let leftLineNumber = 1;
  let rightLineNumber = 1;

  while (leftIndex < leftLines.length || rightIndex < rightLines.length) {
    const leftLine = leftIndex < leftLines.length ? leftLines[leftIndex] : undefined;
    const rightLine = rightIndex < rightLines.length ? rightLines[rightIndex] : undefined;

    if (leftLine === undefined) {
      // 右侧有内容，左侧没有 - 新增
      result.push({
        type: 'added',
        rightLineNumber: rightLineNumber++,
        rightContent: rightLine
      });
      rightIndex++;
    } else if (rightLine === undefined) {
      // 左侧有内容，右侧没有 - 删除
      result.push({
        type: 'removed',
        leftLineNumber: leftLineNumber++,
        leftContent: leftLine
      });
      leftIndex++;
    } else if (normalizeContent(leftLine) === normalizeContent(rightLine)) {
      // 内容相同
      result.push({
        type: 'equal',
        leftLineNumber: leftLineNumber++,
        rightLineNumber: rightLineNumber++,
        leftContent: leftLine,
        rightContent: rightLine
      });
      leftIndex++;
      rightIndex++;
    } else {
      // 内容不同 - 修改
      result.push({
        type: 'modified',
        leftLineNumber: leftLineNumber++,
        rightLineNumber: rightLineNumber++,
        leftContent: leftLine,
        rightContent: rightLine
      });
      leftIndex++;
      rightIndex++;
    }
  }

  return result;
}

// 标准化内容（用于比较）
function normalizeContent(content: string): string {
  let normalized = content;
  
  if (ignoreWhitespace.value) {
    normalized = normalized.replace(/\s+/g, ' ').trim();
  }
  
  if (ignoreCase.value) {
    normalized = normalized.toLowerCase();
  }
  
  return normalized;
}

// 关闭弹窗
function closeModal() {
  emit('close');
}

// 清空内容
function clearContent() {
  leftJson.value = '';
  rightJson.value = '';
}

// 交换左右内容
function swapContent() {
  const temp = leftJson.value;
  leftJson.value = rightJson.value;
  rightJson.value = temp;
  
  const tempTitle = leftTitle.value;
  leftTitle.value = rightTitle.value;
  rightTitle.value = tempTitle;
}

// 格式化JSON
function formatJson(side: 'left' | 'right') {
  try {
    if (side === 'left' && leftJson.value) {
      const parsed = JSON.parse(leftJson.value);
      leftJson.value = JSON.stringify(parsed, null, 2);
    } else if (side === 'right' && rightJson.value) {
      const parsed = JSON.parse(rightJson.value);
      rightJson.value = JSON.stringify(parsed, null, 2);
    }
  } catch (error) {
    console.error('JSON格式化失败:', error);
  }
}

// 统计信息
const stats = computed(() => {
  const diff = diffResult.value;
  const added = diff.filter(line => line.type === 'added').length;
  const removed = diff.filter(line => line.type === 'removed').length;
  const modified = diff.filter(line => line.type === 'modified').length;
  const equal = diff.filter(line => line.type === 'equal').length;
  
  return { added, removed, modified, equal, total: diff.length };
});
</script>

<template>
  <div v-if="visible" class="modal-overlay" @click="closeModal">
    <div class="modal-container" @click.stop>
      <!-- 头部 -->
      <div class="modal-header">
        <h2 class="modal-title">📊 JSON对比</h2>
        <div class="header-controls">
          <div class="stats">
            <span class="stat added">+{{ stats.added }}</span>
            <span class="stat removed">-{{ stats.removed }}</span>
            <span class="stat modified">~{{ stats.modified }}</span>
          </div>
          <button @click="closeModal" class="close-btn">×</button>
        </div>
      </div>

      <!-- 工具栏 -->
      <div class="toolbar">
        <div class="toolbar-left">
          <button @click="clearContent" class="btn btn-secondary">🗑️ 清空</button>
          <button @click="swapContent" class="btn btn-secondary">🔄 交换</button>
          <button @click="formatJson('left')" class="btn btn-secondary">✨ 格式化左侧</button>
          <button @click="formatJson('right')" class="btn btn-secondary">✨ 格式化右侧</button>
        </div>
        <div class="toolbar-right">
          <label class="checkbox-label">
            <input type="checkbox" v-model="showLineNumbers">
            显示行号
          </label>
          <label class="checkbox-label">
            <input type="checkbox" v-model="ignoreWhitespace">
            忽略空白
          </label>
          <label class="checkbox-label">
            <input type="checkbox" v-model="ignoreCase">
            忽略大小写
          </label>
        </div>
      </div>

      <!-- 输入区域 -->
      <div class="input-section">
        <div class="input-panel">
          <div class="panel-header">
            <input v-model="leftTitle" class="title-input" placeholder="左侧标题">
          </div>
          <textarea 
            v-model="leftJson" 
            class="json-textarea"
            placeholder="请输入或粘贴第一个JSON..."
          ></textarea>
        </div>
        <div class="input-panel">
          <div class="panel-header">
            <input v-model="rightTitle" class="title-input" placeholder="右侧标题">
          </div>
          <textarea 
            v-model="rightJson" 
            class="json-textarea"
            placeholder="请输入或粘贴第二个JSON..."
          ></textarea>
        </div>
      </div>

      <!-- 对比结果 -->
      <div class="diff-section">
        <div class="diff-header">
          <div class="diff-title">{{ leftTitle }}</div>
          <div class="diff-title">{{ rightTitle }}</div>
        </div>
        <div class="diff-content">
          <div class="diff-lines">
            <div 
              v-for="(line, index) in diffResult" 
              :key="index"
              :class="['diff-line', line.type]"
            >
              <!-- 左侧 -->
              <div class="line-side left">
                <span v-if="showLineNumbers && line.leftLineNumber" class="line-number">
                  {{ line.leftLineNumber }}
                </span>
                <span class="line-content">
                  {{ line.leftContent || '' }}
                </span>
              </div>
              
              <!-- 右侧 -->
              <div class="line-side right">
                <span v-if="showLineNumbers && line.rightLineNumber" class="line-number">
                  {{ line.rightLineNumber }}
                </span>
                <span class="line-content">
                  {{ line.rightContent || '' }}
                </span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  backdrop-filter: blur(3px);
}

.modal-container {
  background: white;
  border-radius: 12px;
  width: 95vw;
  height: 90vh;
  max-width: 1400px;
  display: flex;
  flex-direction: column;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
  overflow: hidden;
}

/* 头部 */
.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem 1.5rem;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
}

.modal-title {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 600;
}

.header-controls {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.stats {
  display: flex;
  gap: 0.5rem;
}

.stat {
  padding: 0.25rem 0.5rem;
  border-radius: 4px;
  font-size: 0.875rem;
  font-weight: 500;
}

.stat.added {
  background: rgba(46, 160, 67, 0.2);
  color: #2ea043;
}

.stat.removed {
  background: rgba(218, 54, 51, 0.2);
  color: #da3633;
}

.stat.modified {
  background: rgba(251, 188, 5, 0.2);
  color: #fbbc05;
}

.close-btn {
  background: none;
  border: none;
  color: white;
  font-size: 1.5rem;
  cursor: pointer;
  padding: 0.25rem;
  border-radius: 4px;
  transition: background-color 0.2s;
}

.close-btn:hover {
  background: rgba(255, 255, 255, 0.2);
}

/* 工具栏 */
.toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.75rem 1.5rem;
  background: #f8f9fa;
  border-bottom: 1px solid #e9ecef;
}

.toolbar-left {
  display: flex;
  gap: 0.5rem;
}

.toolbar-right {
  display: flex;
  gap: 1rem;
}

.btn {
  padding: 0.5rem 1rem;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 0.875rem;
  transition: all 0.2s;
}

.btn-secondary {
  background: #6c757d;
  color: white;
}

.btn-secondary:hover {
  background: #5a6268;
}

.checkbox-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
  cursor: pointer;
}

/* 输入区域 */
.input-section {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: #e9ecef;
  min-height: 200px;
}

.input-panel {
  background: white;
  display: flex;
  flex-direction: column;
}

.panel-header {
  padding: 0.75rem 1rem;
  background: #f8f9fa;
  border-bottom: 1px solid #e9ecef;
}

.title-input {
  border: none;
  background: none;
  font-weight: 500;
  font-size: 0.875rem;
  width: 100%;
}

.title-input:focus {
  outline: none;
}

.json-textarea {
  flex: 1;
  border: none;
  padding: 1rem;
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: 0.875rem;
  line-height: 1.4;
  resize: none;
  min-height: 150px;
}

.json-textarea:focus {
  outline: none;
}

/* 对比结果 */
.diff-section {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.diff-header {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: #e9ecef;
}

.diff-title {
  padding: 0.75rem 1rem;
  background: #f8f9fa;
  font-weight: 500;
  font-size: 0.875rem;
  border-bottom: 1px solid #e9ecef;
}

.diff-content {
  flex: 1;
  overflow: auto;
  background: white;
}

.diff-lines {
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: 0.875rem;
  line-height: 1.4;
}

.diff-line {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: #e9ecef;
}

.line-side {
  display: flex;
  background: white;
  min-height: 1.4em;
}

.line-number {
  width: 50px;
  padding: 0 0.5rem;
  background: #f8f9fa;
  color: #6c757d;
  text-align: right;
  border-right: 1px solid #e9ecef;
  user-select: none;
  flex-shrink: 0;
}

.line-content {
  padding: 0 0.5rem;
  flex: 1;
  white-space: pre;
}

/* 差异类型样式 */
.diff-line.added .line-side.right {
  background: #d4edda;
}

.diff-line.added .line-side.right .line-content {
  background: #d1ecf1;
}

.diff-line.removed .line-side.left {
  background: #f8d7da;
}

.diff-line.removed .line-side.left .line-content {
  background: #f5c6cb;
}

.diff-line.modified .line-side.left {
  background: #fff3cd;
}

.diff-line.modified .line-side.right {
  background: #d4edda;
}

.diff-line.modified .line-side.left .line-content {
  background: #ffeaa7;
}

.diff-line.modified .line-side.right .line-content {
  background: #d1ecf1;
}
</style>